﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc.Html;
using System.Web.Mvc;
using System.IO;
using Isha.Data;
using Isha.Entities;
using System.Web.Security;
using Isha;
using Isha.Web.Mvc;
using System.Web.Routing;
using System.Text.RegularExpressions;

namespace System.Web.Mvc
{
    public class PredictablePart
    {
        public string Name { get; set; }

        public string AbsolutePath { get; set; }

        public string RelativePath { get; set; }

        public int SelectionPreference { get; set; }

        public int LocationPreference { get; set; }
    }

    public static class PartExtensions
    {
        static List<PredictablePart> Predictables = new List<PredictablePart>();

        public static MvcHtmlString Part(this HtmlHelper _helper, string PartName)
        {
            string portalfactory = "portal_factory";
            string SearchString = "part-*.cshtml";

            DirectoryInfo ViewsFolder = new DirectoryInfo(HttpContext.Current.Server.MapPath(@"~\Views\"));

            if (ViewsFolder.Exists && Predictables.Count == 0)
            {
                foreach (var viewitem in ViewsFolder.GetDirectories())
                {
                    if (viewitem.Name.ToLowerInvariant() == portalfactory && viewitem.GetDirectories("parts").First() != null)
                    {
                        foreach (var fileitem in viewitem.GetDirectories("parts").First().GetFiles(SearchString))
                        {
                            var predictable = new PredictablePart()
                            {
                                Name = Path.GetFileNameWithoutExtension(fileitem.Name.ToLower()),
                                AbsolutePath = @"~\views\" + viewitem.Name.ToLower() + @"\parts\",
                                RelativePath = "../" + viewitem.Name.ToLower() + "/parts/",
                                LocationPreference = 4,
                                SelectionPreference = 5
                            };
                            Predictables.Add(predictable);
                        }
                    }
                    else
                    {
                        foreach (var fileitem in viewitem.GetFiles(SearchString))
                        {
                            var predictable = new PredictablePart()
                            {
                                Name = Path.GetFileNameWithoutExtension(fileitem.Name.ToLower()),
                                AbsolutePath = @"~\views\" + viewitem.Name.ToLower() + @"\",
                                RelativePath = "../" + viewitem.Name.ToLower() + "/"
                            };

                            if (viewitem.Name.ToLower() == "shared")
                                predictable.LocationPreference = 3;
                            else if (viewitem.Name.ToLower() == "parts")
                                predictable.LocationPreference = 2;
                            else
                                predictable.LocationPreference = 1;

                            predictable.SelectionPreference = 5;

                            Predictables.Add(predictable);
                        }
                    }
                }

                foreach (RouteBase routeBase in RouteTable.Routes)
                {
                    var route = (routeBase as Route);

                    if (route.Defaults != null)
                    {
                        string controller = route.Defaults["controller"].ToString();
                        string Part1 = "part-" + controller + "_" + PartName;
                        var Parts1 = Predictables.Where(p => p.Name == Part1.ToLower());

                        foreach (var item in Parts1)
                        {
                            item.SelectionPreference = 2;
                        }

                        string Part2 = "part-" + controller + "_" + @"\w*-" + PartName;
                        var Parts2 = Predictables.Where(p => Regex.Match(p.Name, Part2, RegexOptions.IgnoreCase).Success);

                        foreach (var item in Parts2)
                        {
                            item.SelectionPreference = 3;
                        }
                    }
                }

                Predictables = Predictables.OrderBy(p => p.SelectionPreference).OrderBy(p => p.LocationPreference).ToList();
            }

            ContentItem contentItem = IshaContext.Current.ContentItem;
            string PartName1 = string.Empty;
            string PartName2 = string.Empty;
            string PartName3 = string.Empty;

            if (contentItem.Title != null && contentItem.ParentItemID != null)
            {
                PartName1 = "part-" + contentItem.ParentItemID.Value.ToString() + "_" + contentItem.Link + "-" + PartName;
                var CParts1 = Predictables.Where(p => p.Name == PartName1.ToLower());

                if (CParts1.Count() > 0)
                    return GetPart(_helper, CParts1.First());
            }

            PartName2 = "part-" + _helper.ViewContext.RouteData.Values["Controller"].ToString() + "_" + _helper.ViewContext.RouteData.Values["Action"].ToString() + "-" + PartName;
            var CParts2 = Predictables.Where(p => p.Name == PartName2.ToLower());

            if (CParts2.Count() > 0)
                return GetPart(_helper, CParts2.First());

            PartName3 = "part-" + _helper.ViewContext.RouteData.Values["Controller"].ToString() + "-" + PartName;
            var CParts3 = Predictables.Where(p => p.Name == PartName3.ToLower());

            if (CParts3.Count() > 0)
                return GetPart(_helper, CParts3.First());

            PartName = "part-" + PartName;
            var CParts4 = Predictables.Where(p => p.Name == PartName.ToLower());

            if (CParts4.Count() > 0)
                return GetPart(_helper, CParts4.First());

            return null;
        }

        private static MvcHtmlString GetPart(HtmlHelper _helper, PredictablePart Part)
        {
            if (File.Exists(HttpContext.Current.Server.MapPath(Part.AbsolutePath + Part.Name + ".cshtml"))
                    || File.Exists(HttpContext.Current.Server.MapPath(Part.AbsolutePath + Part.Name + ".vbhtml")))
            {
                return new MvcHtmlString(@"<div class=""part"">" + PartialExtensions.Partial(_helper, Part.RelativePath + Part.Name).ToHtmlString() + "</div>");
            }

            return null;
        }

        public static MvcHtmlString AuthenticatedPart(this HtmlHelper _helper, string PartName, string Roles)
        {
            bool IsInRole = false;

            foreach (var item in Roles.Split(','))
            {
                if (HttpContext.Current.User.IsInRole(item))
                    IsInRole = true;
            }

            if (IsInRole)
                return PartExtensions.Part(_helper, PartName);

            return new MvcHtmlString("");
        }

        public static MvcHtmlString AuthenticatedPart(this HtmlHelper _helper, string PartName)
        {
            bool IsInRole = false;

            if (HttpContext.Current.Request.IsAuthenticated)
                IsInRole = true;

            if (IsInRole)
                return PartExtensions.Part(_helper, PartName);

            return new MvcHtmlString("");
        }
    }
}